Add a resumable PowerShell setup flow for Windows developer machines - #93
Add a resumable PowerShell setup flow for Windows developer machines#93AmirMS (AmelBawa-msft) wants to merge 19 commits into
Conversation
The release-copy updates move to a separate PR, so this branch no longer touches windows-dev-config/. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: fa27b7a2-0eb1-4970-927c-340739ecbdc1
There was a problem hiding this comment.
Pull request overview
Replaces the DSC-based Calm OS flow with a modular, idempotent PowerShell setup that supports elevation and reboot resumption.
Changes:
- Adds bootstrap, orchestration, setup phases, and shared helpers.
- Adds WSL reboot/resume, package, registry, Terminal, font, and Copilot configuration.
- Updates manifests and documentation while removing the old DSC implementation.
Reviewed changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
.gitignore |
Ignores setup tally state. |
README.md |
Documents the new PowerShell flow. |
src/docs/development.md |
Describes PowerShell-native flow conventions. |
src/future/cmdpal/README.md |
Notes extension launch limitations. |
src/manifest.yml |
Points Calm OS at the new entry script. |
src/tests/calm-os/probe.ps1 |
Updates smoke-test commentary. |
src/windows-dev-config/README.md |
Rewrites usage and configuration documentation. |
src/windows-dev-config/bootstrap.ps1 |
Downloads and verifies the setup payload. |
src/windows-dev-config/dev-config.ps1 |
Orchestrates setup phases and reporting. |
src/windows-dev-config/dev-config.winget |
Removes the legacy DSC configuration. |
src/windows-dev-config/install.ps1 |
Removes the legacy install shim. |
steps/_console.ps1 |
Adds logging and pause helpers. |
steps/_elevation.ps1 |
Adds elevation and single-instance handling. |
steps/_environment.ps1 |
Adds process, PATH, TLS, and file helpers. |
steps/_pwsh-bootstrap.ps1 |
Bootstraps and relaunches under PowerShell 7. |
steps/_reboot-resume.ps1 |
Registers post-reboot continuation. |
steps/_registry.ps1 |
Adds registry helpers. |
steps/_resume-wrapper.ps1 |
Relays resumed-run output. |
steps/_retry.ps1 |
Adds retry handling. |
steps/_step-runner.ps1 |
Implements check/apply/verify execution. |
steps/_terminal.ps1 |
Manages Terminal settings JSON. |
steps/_winget.ps1 |
Manages WinGet front ends and packages. |
steps/copilot.ps1 |
Configures Copilot integrations. |
steps/edge.ps1 |
Applies Edge policies. |
steps/fonts.ps1 |
Installs and configures Cascadia fonts. |
steps/packages.ps1 |
Defines the package set. |
steps/powershell-profile.ps1 |
Adds Oh My Posh initialization. |
steps/prerequisites.ps1 |
Verifies PowerShell and WinGet. |
steps/registry-explorer.ps1 |
Applies Explorer settings. |
steps/registry-system.ps1 |
Applies system settings. |
steps/registry-taskbar-search.ps1 |
Applies taskbar and search settings. |
steps/terminal.ps1 |
Configures Terminal defaults and theme. |
steps/wsl.ps1 |
Installs WSL, reboots, and installs Ubuntu. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if ($Script:DevConfigWinGetMode -eq 'Cli') { | ||
| $listed = Invoke-DevConfigWingetCli -Arguments @('list', '--id', $Id, '--exact', '--accept-source-agreements') | ||
| if ($listed.ExitCode -eq $Script:DevConfigWingetNotFound) { | ||
| return $false | ||
| } | ||
| if ($listed.ExitCode -ne 0) { | ||
| throw "winget list $Id failed with exit code $($listed.ExitCode)" | ||
| } | ||
| # winget list --upgrade-available exits 0 for any installed package, with or without an upgrade. | ||
| return $true |
There was a problem hiding this comment.
CLI mode now matches module mode:
return -not (Test-DevConfigWingetUpgradeAvailable -Id $Id)The helper runs winget list --upgrade-available and matches the package id. Exit codes are no use here — winget returns 0 either way — and the messages are localized, so the id is the only stable signal.
Checked against real winget on a VM, plus unit tests for the upgrade-available, no-match and failed-query cases.
| # Terminal settings are JSONC, so comments are removed before ConvertFrom-Json. | ||
| $clean = [regex]::Replace($raw, '/\*[\s\S]*?\*/', '') | ||
| $clean = [regex]::Replace($clean, '(?m)^\s*//.*$', '') |
| if ($alreadyDone) { | ||
| $Script:DevConfigTally.AlreadyOk++ | ||
| } | ||
| [pscustomobject]@{ Step = $step; AlreadyDone = $alreadyDone } |
| try { | ||
| [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $dest, $true) | ||
| } catch { | ||
| # A font the system has already loaded can't be overwritten, and it is the same version. | ||
| if (-not (Test-Path $dest)) { throw } | ||
| Write-Host ' (keeping the copy already in place)' -ForegroundColor DarkGray |
| @{ Name = 'BluetoothOff'; KeyPath = 'HKCU\Control Panel\Bluetooth'; ValueName = 'Notification Area Icon'; Value = 0; Description = 'Hide Bluetooth icon in taskbar notification area' } | ||
| @{ Name = 'EndTask'; KeyPath = $advanced; ValueName = 'TaskbarEndTask'; Value = 1; Description = 'Enable "End Task" on right-click of taskbar icons' } | ||
| @{ Name = 'WebSearchOff'; KeyPath = 'HKCU\SOFTWARE\Policies\Microsoft\Windows\Explorer'; ValueName = 'DisableSearchBoxSuggestions'; Value = 1; Description = 'Disable web search in Start/Search' } | ||
| @{ Name = 'SearchHightlightOff'; KeyPath = 'HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\SearchSettings'; ValueName = 'IsDynamicSearchBoxEnabled'; Value = 0; Description = 'Disable Show search highlights' } |
| | - | ------------ | ---------------- | | ||
| | 1 | A UAC prompt appears | **Accept it.** Most of the settings are machine-wide and need Administrator. | | ||
| | 2 | PowerShell 7 is installed if it isn't already, and the setup restarts itself on it | None | | ||
| | 3 | Ten phases run: packages, Windows settings, fonts, Terminal, prompt, Copilot | None. Long silent stretches during big downloads are normal — a "still working" note prints every minute | |
| if (Test-Path -LiteralPath $Path) { | ||
| Copy-Item -LiteralPath $Path -Destination "$Path.bak" -Force |
| # The current WSL package supports --version; the inbox WSL returns a nonzero exit code. | ||
| function Test-DevConfigWslPlatformActive { | ||
| return ((Get-DevConfigWslExitCode -Arguments @('--version')) -eq 0) |
1703f36 to
9c0e1ea
Compare
| } | ||
|
|
||
| $steps += New-DevConfigStep -Name 'PowerToysAOT' -Description 'Turn off PowerToys always-on-top notifications' ` | ||
| -Check { Test-DevConfigRegistryValue -KeyPath 'HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\PowerToys' -ValueName 'Enabled' -Value 0 } ` |
There was a problem hiding this comment.
Based on trying this out, I think this should be Microsoft.PowerToysWin32
Introduces a PowerShell implementation of the developer workstation setup that
runs from a single command, checks every change before applying it, and continues
across the reboot WSL requires.